package email

import (
	"context"
	"fmt"
	"go-caipu/pkg/tsdb/email/models"
	"gorm.io/gorm"
	"log"
	"time"
)

// MailSender 邮件发送接口
type MailSender interface {
	Send(email *models.Email) error
	TestDial() error
}

// CallbackHandler 回调处理接口
type CallbackHandler interface {
	OnSuccess(email *models.Email) error
	OnFailure(email *models.Email, err error) error
}

// Storage 存储接口
type Storage interface {
	Save(email *models.Email) error
	Update(email *models.Email) error
	GetPending() ([]*models.Email, error)
}

// MailService 邮件服务
type MailService struct {
	db            *gorm.DB // 数据库连接
	sender        MailSender
	callback      CallbackHandler
	retryInterval time.Duration
	maxRetries    int
	queue         chan *models.Email
	workers       int
	retryQueue    chan *models.Email
	ctx           context.Context
	cancel        context.CancelFunc
}

// Init 初使化系统
func Init(db *gorm.DB) *MailService {
	ctx, cancel := context.WithCancel(context.Background())
	return &MailService{
		callback:      NewHTTPCallbackHandler(),
		db:            db,
		retryInterval: 5 * time.Minute,
		maxRetries:    3,
		queue:         make(chan *models.Email, 100),
		workers:       3,
		retryQueue:    make(chan *models.Email, 50),
		ctx:           ctx,
		cancel:        cancel,
	}
}

// UpdateService 创建邮件服务
func (s *MailService) UpdateService(sender MailSender, opts ...Option) *MailService {
	s.sender = sender
	for _, opt := range opts {
		opt(s)
	}
	return s
}

// Option 配置选项
type Option func(*MailService)

// WithRetryInterval 重试间隔
func WithRetryInterval(interval time.Duration) Option {
	return func(m *MailService) {
		m.retryInterval = interval
	}
}

// WithMaxRetries 最大重试次数
func WithMaxRetries(maxRetries int) Option {
	return func(m *MailService) {
		m.maxRetries = maxRetries
	}
}

// WithWorkers 工作线程数
func WithWorkers(workers int) Option {
	return func(m *MailService) {
		m.workers = workers
	}
}
func (ms *MailService) Start() error {
	if err := ms.db.AutoMigrate(&models.Email{}); err != nil {
		return err
	}
	//加载待发送邮件
	var pendingEmails []*models.Email
	result := ms.db.Where("status = ? OR (status = ? AND attempts < ?)",
		"pending", "failed", ms.maxRetries).Find(&pendingEmails)
	if result.Error != nil {
		return fmt.Errorf("failed to get pending emails: %w", result.Error)
	}
	// 将待发送邮件加入队列
	for _, pendingEmail := range pendingEmails {
		ms.queue <- pendingEmail
	}
	// 启动工作线程
	for i := 0; i < ms.workers; i++ {
		go ms.worker()
	}
	//启动重试线程
	go ms.retryWorker()

	return nil
}

// worker 工作goroutine
func (ms *MailService) worker() {
	for {
		select {
		case email := <-ms.queue:
			if ms.sender == nil {
				log.Printf("worker：Mail sender is not initialized")
				continue
			}
			ms.processEmail(email)
		case <-ms.ctx.Done():
			return
		}
	}
}

// retryWorker 重试工作goroutine
func (ms *MailService) retryWorker() {
	ticker := time.NewTicker(ms.retryInterval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			var pendingEmails []models.Email
			result := ms.db.Where("status = ? OR (status = ? AND attempts < ?)",
				"pending", "failed", ms.maxRetries).Find(&pendingEmails)
			if result.Error != nil {
				log.Printf("Error getting pending emails: %v", result.Error)
				continue
			}

			for i := range pendingEmails {
				ms.retryQueue <- &pendingEmails[i]
			}
		case email := <-ms.retryQueue:
			if ms.sender == nil {
				log.Printf("retryWorker：Mail sender is not initialized")
				continue
			}
			ms.processEmail(email)
		case <-ms.ctx.Done():
			return
		}
	}
}

// processEmail 处理邮件发送
func (ms *MailService) processEmail(email *models.Email) {
	if ms.sender == nil {
		return
	}
	email.Attempts++
	email.LastAttempt = time.Now()

	err := ms.sender.Send(email)
	if err != nil {
		email.Status = "failed"
		email.ErrorMessage = err.Error()
		log.Printf("Failed to send email %s (attempt %d): %v", email.MessageID, email.Attempts, err)

		if err := ms.db.Save(email).Error; err != nil {
			log.Printf("Failed to update email status: %v", err)
		}

		if email.Attempts < ms.maxRetries {
			// 加入重试队列
			time.AfterFunc(ms.retryInterval, func() {
				ms.retryQueue <- email
			})
		} else {
			// 达到最大重试次数，回调业务系统
			if err := ms.callback.OnFailure(email, err); err != nil {
				log.Printf("Failed to execute failure callback: %v", err)
			}
		}
		return
	}
	// 发送成功
	email.Status = "success"
	email.ErrorMessage = ""
	if err := ms.db.Save(email).Error; err != nil {
		log.Printf("Failed to update email status: %v", err)
	}

	// 回调业务系统
	if err := ms.callback.OnSuccess(email); err != nil {
		log.Printf("Failed to execute success callback: %v", err)
	}
}

// Send 发送邮件
func (ms *MailService) Send(email *models.Email) error {
	email.Status = "pending"
	email.Attempts = 0
	email.LastAttempt = time.Now()

	if err := ms.db.Create(email).Error; err != nil {
		return fmt.Errorf("failed to save email: %w", err)
	}
	ms.queue <- email
	return nil
}

// Stop 停止服务
func (ms *MailService) Stop() {
	fmt.Println("Stopping MailService")
	ms.cancel()
	close(ms.queue)
	close(ms.retryQueue)
}
func (ms *MailService) TestDial() error {
	return ms.sender.TestDial()
}
